package com.ruoyi.web.controller.system;

import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.constant.HttpStatus;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.core.domain.entity.SysRole;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.li.work.domain.vo.WorkDeptUserVO;
import com.ruoyi.li.work.domain.vo.revisePwdVO;
import com.ruoyi.li.work.service.ISysDeptService;
import com.ruoyi.li.work.service.ISysPostService;
import com.ruoyi.li.work.service.ISysRoleService;
import com.ruoyi.li.work.service.ISysUserService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.ArrayUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.util.CollectionUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * 用户信息
 *
 * @author ruoyi
 */
@RestController
@RequestMapping("/system/user")
@Api(tags = "ry-用户列表")
public class SysUserController extends BaseController {
    @Autowired
    private ISysUserService userService;

    @Autowired
    private ISysRoleService roleService;

    @Autowired
    private ISysDeptService deptService;

    @Autowired
    private ISysPostService postService;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private RedisCache redisCache;

    /**
     * 获取用户列表
     */
    // @PreAuthorize("@ss.hasPermi('system:user:list')")
    @GetMapping("/list")
    @ApiOperation("获取用户列表(学校管理员)")
    public TableDataInfo list(SysUser user) {
        user.setRemark("0");
        List<SysUser> list = userService.selectUserList(user);
        return getDataTable(list);
    }

    /**
     * 获取用户列表
     */
//    @PreAuthorize("@ss.hasPermi('system:user:listAdminAll')")
    @GetMapping("/listAdminAll")
    @ApiOperation("获取用户列表(总管理员)")
    public TableDataInfo listAdminAll(SysUser user) {
        user.setRemark("1");
        startPage();
        List<SysUser> list = userService.selectUserList(user);
        return getDataTable(list);
    }

    @GetMapping("/name")
    @ApiOperation("获取用户列表")
    public AjaxResult name() {
        return userService.selectUserName();
    }

    @GetMapping("/nameUrl")
    @ApiOperation(value = "用户头像", notes = "根据用户账户获取用户头像")
    public AjaxResult nameUrl(String userName) {
        return userService.selectNameUrl(userName);
    }


    @Log(title = "用户管理", businessType = BusinessType.EXPORT)
    @PreAuthorize("@ss.hasPermi('system:user:export')")
    @PostMapping("/export")
    @ApiOperation("导出用户数据")
    public void export(HttpServletResponse response, SysUser user) {
        List<SysUser> list = userService.selectUserList(user);
        ExcelUtil<SysUser> util = new ExcelUtil<SysUser>(SysUser.class);
        util.exportExcel(response, list, "用户数据");
    }

    @Log(title = "用户管理", businessType = BusinessType.IMPORT)
    @PreAuthorize("@ss.hasPermi('system:user:import')")
    @PostMapping("/importData")
    @ApiOperation("导出用户数据")
    public AjaxResult importData(MultipartFile file, boolean updateSupport) throws Exception {
        ExcelUtil<SysUser> util = new ExcelUtil<SysUser>(SysUser.class);
        List<SysUser> userList = util.importExcel(file.getInputStream());
        String operName = getUsername();
        String message = userService.importUser(userList, updateSupport, operName);
        return success(message);
    }

    @PostMapping("/importTemplate")
    public void importTemplate(HttpServletResponse response) {
        ExcelUtil<SysUser> util = new ExcelUtil<SysUser>(SysUser.class);
        util.importTemplateExcel(response, "用户数据");
    }

    /**
     * 根据用户编号获取详细信息
     */
//    @PreAuthorize("@ss.hasPermi('system:user:query')")
    @GetMapping(value = {"/", "/{userId}"})
    @ApiOperation("根据用户编号获取详细信息")
    public AjaxResult getInfo(@PathVariable(value = "userId", required = false) Long userId) {
        if(null == userId){
            userId = getUserId();
        }
        userService.checkUserDataScope(userId);
        AjaxResult ajax = AjaxResult.success();
        List<SysRole> roles = roleService.selectRoleAll();
        ajax.put("roles", SysUser.isAdmin(userId) ? roles : roles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList()));
        ajax.put("posts", postService.selectPostAll());
        if (StringUtils.isNotNull(userId)) {
            SysUser sysUser = userService.selectUserById(userId);
            ajax.put(AjaxResult.DATA_TAG, sysUser);
            ajax.put("postIds", postService.selectPostListByUserId(userId));
            ajax.put("roleIds", sysUser.getRoles().stream().map(SysRole::getRoleId).collect(Collectors.toList()));
        }
        return ajax;
    }

    /**
     * 新增用户(学校管理员)
     */
    @PreAuthorize("@ss.hasPermi('system:user:add')")
    @Log(title = "用户管理", businessType = BusinessType.INSERT)
    @PostMapping
    @ApiOperation("新增用户(学校管理员)")
    public AjaxResult add(@RequestBody List<SysUser> users) {
        String error = null;
        Set<String> userNameSet = new HashSet<>();
        for (SysUser user : users) {
            // 检查列表中是否有重复的 userName
            if (!userNameSet.add(user.getUserName())) {
                error = "账号'" + user.getUserName() + "'在重复，上传失败";
                break;
            }
            error = validateUser(user, true,true);
            if (error != null) {
                break;
            }
            user.setCreateBy(getUsername());
            user.setPassword(SecurityUtils.encryptPassword("123456")); // 新建账号默认密码为123456
            user.setRemark("0");
        }
        if (error != null) {
            return error(error);
        }
        redisCache.deleteObject("offlineNameList");
        return userService.insertUser(users);
    }


    /**
     * 新增用户(总管理员)
     */
//    @PreAuthorize("@ss.hasPermi('system:user:addAll')")
    @Log(title = "用户管理", businessType = BusinessType.INSERT)
    @PostMapping("/addAll")
    @ApiOperation("新增用户(总管理员)")
    public AjaxResult addAll(@RequestBody List<SysUser> users) {
        String error = null;
        Set<String> userNameSet = new HashSet<>();
        for (SysUser user : users) {
            // 检查列表中是否有重复的 userName
            if (!userNameSet.add(user.getUserName())) {
                error = "账号'" + user.getUserName() + "'在重复，上传失败";
                break;
            }
            error = validateUser(user, true,false);
            if (error != null) {
                break;
            }
            user.setCreateBy(getUsername());
            user.setPassword(SecurityUtils.encryptPassword("123456")); // 新建账号默认密码为123456
            user.setRemark("1");
        }
        if (error != null) {
            return error(error);
        }
        return userService.insertUser(users);
    }


    /**
     * 注册用户
     */
//    @PreAuthorize("@ss.hasPermi('system:user:add')")
    @Log(title = "注册用户", businessType = BusinessType.INSERT)
    @PostMapping("/register")
    @ApiOperation("注册用户")
    public AjaxResult register(@RequestBody SysUser user) {
        String error = validateUserRegister(user, true);
//        if (null!=user.getDept().getDeptName()&&!user.getDept().getDeptName().equals("")) {
//            Long deptId=deptService.selectdeptName(user.getDept().getDeptName());
//            user.setDeptId(deptId);
//        }
        if (error != null) {
            return error(error);
        }
        if (Pattern.matches("\\d{11}", user.getEmail())) {
            user.setPhonenumber(user.getEmail());
            user.setEmail("");
        }
        user.setLoginIp(null);
        user.setPassword(SecurityUtils.encryptPassword(user.getPassword()));// 加密存放密码
        List<SysUser> sysUsers = new ArrayList<>();
        sysUsers.add(user);
        user.setUserType("1");// 注册用户
        return userService.insertUser(sysUsers);
    }

    /**
     * 找回密码
     */
//    @PreAuthorize("@ss.hasPermi('system:user:add')")
    @Log(title = "找回密码", businessType = BusinessType.INSERT)
    @PostMapping("/retrievePassword")
    @ApiOperation("找回密码")
    public AjaxResult retrievePassword(@RequestBody SysUser user) {
        String password = user.getPassword();
        String checkEmail = user.getEmail();
        if (null != checkEmail && !checkEmail.equals("")) {
            String loginIp = user.getLoginIp();
            List<SysUser> sysUsers = userService.selectList(checkEmail);
            if (CollectionUtils.isEmpty(sysUsers)) {
                return error("该邮箱/手机号未注册");
            }
            user = userService.selectList(checkEmail).get(0);
            if (user == null) {
                return error("该邮箱/手机号未注册");
            }
            user.setLoginIp(loginIp);
            String key = "msg_" + checkEmail;
            ValueOperations<String, String> valueOperations = stringRedisTemplate.opsForValue();
            String verifyCode = valueOperations.get(key);
            if (checkEmail.contains("@") || Pattern.matches("\\d{11}", checkEmail)) {// 邮箱//短信校验
                if (verifyCode == null) {
                    return error("请发送验证码");
                }
                if (null != user.getLoginIp() && !user.getLoginIp().equals("") && verifyCode.equals(user.getLoginIp())) {// 清除验证码记录
                    String countKey = "msg_count_" + checkEmail; // 定义计数器 key
                    // 删除 Redis 中的 key
                    stringRedisTemplate.delete(key);
                    stringRedisTemplate.delete(countKey);
                } else {
                    return error("验证码错误");
                }
            } else {
                return error("手机号/邮箱账错误");
            }
        } else {
            return error("手机号/邮箱不能为空");
        }
        user.setPassword(SecurityUtils.encryptPassword(password));// 加密存放密码
        int i1 = userService.updateUserPassword(user);
        if (i1 > 0) {
            return new AjaxResult(HttpStatus.SUCCESS, "修改成功");
        }
        return error("修改失败");
    }

    /**
     * 验证用户信息的公共方法
     *
     * @param user  要验证的用户对象
     * @param isNew 是否为新用户
     * @return 错误信息，如果验证通过则返回 null
     */
    private String validateUserRegister(SysUser user, boolean isNew) {
        // 检查昵称是否为空且长度是否超过10位，并验证其只包含英文和数字
        if (user.getNickName() == null || user.getNickName().isEmpty() || user.getNickName().length() > 30 ||
                !Pattern.matches("^[\\u4e00-\\u9fa5a-zA-Z]+$", user.getNickName())) {
            return "姓名'" + user.getNickName() + "'不能为空且长度不能超过30位，且只能包含汉字和英文";
        }
        // 检查用户名是否为空且长度是否超过15位，并验证其只包含汉字和英文字符
        if (user.getUserName() == null || user.getUserName().isEmpty() || user.getUserName().length() > 20 ||
                !Pattern.matches("^[a-zA-Z0-9]{6,20}$", user.getUserName())) {
            return "账号'" + user.getUserName() + "'不能为空且6-20位(字母+数字)";
        }
//        if (user.getPassword() == null||user.getPassword().isEmpty()||
//                !Pattern.matches("((?=.*\\\\d)(?=.*[a-zA-Z])(?=.*[@#$%^&+=!.~/*-_?]).{8,16})", user.getPassword())) {
//            return "密码必须为8-16位（字母+数字+特殊字符）";
//        }
        // 检查角色ID是否为空
        if (user.getRoleId() == null) {
            return "请为账号'" + user.getUserName() + "'选择角色";
        }
        // 新增用户时检查用户名是否唯一
        if (isNew && !userService.checkUserNameUnique(user)) {
            return "新增用户'" + user.getNickName() + "'失败,原因：账号'" + user.getUserName() + "'已存在";
        }
        if (null != user.getEmail() && !user.getEmail().equals("")) {
            List<SysUser> userList = userService.selectList(user.getEmail());
            if (userList.size() > 0) {
                return "当前绑定方式已使用，请换验证方式";
            }
            String key = "msg_" + user.getEmail();
            ValueOperations<String, String> valueOperations = stringRedisTemplate.opsForValue();
            String verifyCode = valueOperations.get(key);
            if (user.getEmail().contains("@") || Pattern.matches("\\d{11}", user.getEmail())) {// 邮箱//短信校验
                if (verifyCode == null) {
                    return "请发送验证码";
                }
                if (null != user.getLoginIp() && !user.getLoginIp().equals("") && verifyCode.equals(user.getLoginIp())) {// 清除验证码记录
                    String countKey = "msg_count_" + user.getEmail(); // 定义计数器 key
                    // 删除 Redis 中的 key
                    stringRedisTemplate.delete(key);
                    stringRedisTemplate.delete(countKey);
                }  else {
                    return "验证码错误";
                }
            } else {
                return "手机号/邮箱账错误";
            }
        } else {
            return "手机号/邮箱不能为空";
        }
        return null;
    }

    /**
     * 后台校验验证码
     */
    @GetMapping("/validateCode")
    @ApiOperation("后台校验验证码")
    public AjaxResult validateCode(String number,String loginIp) {
        if (null != number && !number.equals("")) {
            String key = "msg_" + number;
            ValueOperations<String, String> valueOperations = stringRedisTemplate.opsForValue();
            String verifyCode = valueOperations.get(key);
            if (number.contains("@") || Pattern.matches("\\d{11}", number)) {// 邮箱//短信校验
                if (verifyCode == null) {
                    return AjaxResult.error("请发送验证码");
                }
                if (null != loginIp && !loginIp.equals("") && verifyCode.equals(loginIp)) {// 清除验证码记录
                    String countKey = "msg_count_" + number; // 定义计数器 key
                    // 删除 Redis 中的 key
                    stringRedisTemplate.delete(key);
                    stringRedisTemplate.delete(countKey);
                } else {
                    return AjaxResult.error("验证码错误");
                }
            } else {
                return AjaxResult.error("手机号/邮箱账错误");
            }
        } else {
            return AjaxResult.error("手机号/邮箱不能为空");
        }
        return AjaxResult.success();
    }

    /**
     * 修改用户
     */
    @PreAuthorize("@ss.hasPermi('system:user:edit')")
    @Log(title = "用户管理", businessType = BusinessType.UPDATE)
    @PutMapping
    @ApiOperation("修改用户")
    public AjaxResult edit(@Validated @RequestBody SysUser user) {
        userService.checkUserAllowed(user);
        userService.checkUserDataScope(user.getUserId());
        String error = validateUser(user, false,false);
        if (error != null) {
            return error(error);
        }
        user.setUpdateBy(getUsername());
        return toAjax(userService.updateUser(user));
    }
    /**
     * 修改用户
     */
//    @PreAuthorize("@ss.hasPermi('system:user:examine')")
//    @Log(title = "用户管理", businessType = BusinessType.UPDATE)
//    @PutMapping("/examine")
//    @ApiOperation("审核用户")
//    public AjaxResult examine(Long userId,String status) {
//        SysUser sysUser = new SysUser();
//        sysUser.setUserId(userId);
//        sysUser.setStatus(status);
//        return toAjax(userService.updateUserStatus(sysUser));
//    }

    /**
     * 验证用户信息的公共方法
     *
     * @param user  要验证的用户对象
     * @param isNew 是否为新用户
     * @return 错误信息，如果验证通过则返回 null
     */
    private String validateUser(SysUser user, boolean isNew,boolean isSchoolAdmin) {
        // 检查昵称是否为空且长度是否超过10位，并验证其只包含英文和数字
        if (user.getNickName() == null || user.getNickName().isEmpty() || user.getNickName().length() > 30 ||
                !Pattern.matches("^[\\u4e00-\\u9fa5a-zA-Z]+$", user.getNickName())) {
            return "姓名'" + user.getNickName() + "'不能为空且长度不能超过30位，且只能包含汉字和英文";
        }
        // 检查用户名是否为空且长度是否超过15位，并验证其只包含汉字和英文字符
        if (user.getUserName() == null || user.getUserName().isEmpty() || user.getUserName().length() > 20 ||
                !Pattern.matches("^[a-zA-Z0-9]+$", user.getUserName())) {
            return "账号'" + user.getUserName() + "'不能为空且长度不能超过20位，且只能包含英文和数字";
        }
        // 检查角色ID是否为空
        if (user.getRoleIds() == null) {
            return "请为账号'" + user.getUserName() + "'选择角色";
        }
        // 检查部门ID是否为空
        if(isSchoolAdmin){
            if (user.getClassId() == null && (user.getRoleIds().toString().equals("4") || user.getRoleIds().toString().equals("3"))) {
                return "请为账号'" + user.getUserName() + "'选择班级";
            }
        }
        // 新增用户时检查用户名是否唯一
        if (isNew && !userService.checkUserNameUnique(user)) {
            return "新增用户'" + user.getNickName() + "'失败,原因：账号'" + user.getUserName() + "'已存在";
        }
        // 修改用户时检查手机号和邮箱是否唯一
        if (!isNew) {
            if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(user)) {
                return "修改用户'" + user.getUserName() + "'失败，手机号码已存在";
            }
            if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(user)) {
                return "修改用户'" + user.getUserName() + "'失败，邮箱账号已存在";
            }
            if (!userService.checkUserNameUnique(user)) {
                return "修改用户'" + user.getNickName() + "'失败,原因：账号'" + user.getUserName() + "'已存在";
            }
        }
        return null;
    }

    /**
     * 删除用户
     */
    @PreAuthorize("@ss.hasPermi('system:user:remove')")
    @Log(title = "用户管理", businessType = BusinessType.DELETE)
    @DeleteMapping("/{userIds}")
    @ApiOperation("删除用户")
    public AjaxResult remove(@PathVariable Long[] userIds) {
        if (ArrayUtils.contains(userIds, getUserId())) {
            return error("当前用户不能删除");
        }
        return toAjax(userService.deleteUserByIds(userIds));
    }

    /**
     * 重置密码
     */
    @PreAuthorize("@ss.hasPermi('system:user:resetPwd')")
    @Log(title = "用户管理", businessType = BusinessType.UPDATE)
    @PutMapping("/resetPwd")
    @ApiOperation("重置密码")
    public AjaxResult resetPwd(@RequestBody SysUser user) {
        userService.checkUserAllowed(user);
        userService.checkUserDataScope(user.getUserId());
        user.setPassword(SecurityUtils.encryptPassword(user.getPassword()));
        user.setUpdateBy(getUsername());
        return toAjax(userService.resetPwd(user));
    }

    /**
     * 修改密码
     */
//    @PreAuthorize("@ss.hasPermi('system:user:revisePwd')")
    @Log(title = "用户管理", businessType = BusinessType.UPDATE)
    @PutMapping("/revisePwd")
    @ApiOperation("修改密码")
    public AjaxResult revisePwd(@RequestBody revisePwdVO revisePwdVO) {
        int i = userService.revisePwd(revisePwdVO.getNewPassword(), revisePwdVO.getOldPassword());
        if (i > 0) {
            return success();
        }
        return error("原始密码错误");
    }

    /**
     * 状态修改
     */
    @PreAuthorize("@ss.hasPermi('system:user:edit')")
    @Log(title = "用户管理", businessType = BusinessType.UPDATE)
    @PutMapping("/changeStatus")
    @ApiOperation("状态修改")
    public AjaxResult changeStatus(@RequestBody SysUser user) {
        System.out.println(user);
        userService.checkUserAllowed(user);
        userService.checkUserDataScope(user.getUserId());
        user.setUpdateBy(getUsername());
        return toAjax(userService.updateUserStatus(user));
    }

    /**
     * 根据用户编号获取授权角色
     */
    @PreAuthorize("@ss.hasPermi('system:user:query')")
    @GetMapping("/authRole/{userId}")
    @ApiOperation("根据用户编号获取授权角色")
    public AjaxResult authRole(@PathVariable("userId") Long userId) {
        AjaxResult ajax = AjaxResult.success();
        SysUser user = userService.selectUserById(userId);
        List<SysRole> roles = roleService.selectRolesByUserId(userId);
        ajax.put("user", user);
        ajax.put("roles", SysUser.isAdmin(userId) ? roles : roles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList()));
        return ajax;
    }

    /**
     * 用户授权角色
     */
    @PreAuthorize("@ss.hasPermi('system:user:edit')")
    @Log(title = "用户管理", businessType = BusinessType.GRANT)
    @PutMapping("/authRole")
    @ApiOperation("用户授权角色")
    public AjaxResult insertAuthRole(Long userId, Long roleIds) {
        userService.checkUserDataScope(userId);
        userService.insertUserAuth(userId, roleIds);
        return success();
    }

    /**
     * 获取部门树列表
     */
    @PreAuthorize("@ss.hasPermi('system:user:list')")
    @GetMapping("/deptTree")
    @ApiOperation("获取部门树列表")
    public AjaxResult deptTree(SysDept dept) {
        return success(deptService.selectDeptTreeList(dept));
    }


    @PreAuthorize("@ss.hasPermi('plan:userListAll')")
    @GetMapping("/selectDeptUser")
    @ApiOperation(value = "查询部门下的人员", notes = "查询部门下的人员")
    public AjaxResult selectDeptUser(Long deptId) {
        List<WorkDeptUserVO> userList = userService.selectDeptUser(deptId);
        return success(userList);
    }

    @PreAuthorize("@ss.hasPermi('plan:userList')")
    @GetMapping("/selectDeptUserOwn")
    @ApiOperation(value = "查询自己所属部门", notes = "查询自己所属部门")
    public AjaxResult selectDeptUserOwn(Long deptId) {
        List<WorkDeptUserVO> userList = userService.selectDeptUserOwn(deptId);
        return success(userList);
    }


}
